package lg.minecraft.plugin.pokemonmenu.gui;

import com.cobblemon.mod.common.api.pokemon.PokemonProperties;
import com.cobblemon.mod.common.pokemon.Pokemon;
import lg.minecraft.plugin.cobblemoncore.util.PokemonPropertiesArgumentType;
import lg.minecraft.plugin.library.inventory.ClickInventoryContext;
import lg.minecraft.plugin.library.inventory.InventoryContext;
import lg.minecraft.plugin.pokemonmenu.LGPokemonMenu;
import lg.minecraft.plugin.pokemonmenu.PokemonPlayer;
import lg.minecraft.plugin.pokemonmenu.command.InputType;
import lg.minecraft.plugin.pokemonmenu.display.PokemonDisplayHandler;
import lg.minecraft.plugin.pokemonmenu.handler.input.PlayerInputManager;
import lg.minecraft.plugin.pokemonmenu.manager.DisplayPokemonManger;
import lg.minecraft.plugin.pokemonmenu.manager.PokemonPlayerManger;
import lg.minecraft.plugin.pokemonmenu.util.Position;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;

import java.util.UUID;
import java.util.function.Function;

/**
 * @author langle__
 * @version 1.0
 */
public class PCInventor extends AbstractPokemonInventory {

    private static final int[] GLASS_ARRAY = {6, 8, 15, 17, 24, 26, 33, 35, 42, 44, 45, 47};
    private static final int[] POKEMON_ARRAY = {7, 16, 25, 34, 43, 52, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 14, 18, 19, 20, 21, 22, 23, 27, 28, 29, 30, 31, 32, 36, 37, 38, 39, 40, 41};

    private boolean search = false;
    private int page;

    public PCInventor(UUID targetUUID, int page) {
        super(targetUUID, LGPokemonMenu.getMessage().getGuiTitlePc());
        this.page = page;
    }

    @Override
    public void onDrawInventory(Player player) {
        saveAndClearMainHand(player.getInventory());
        PokemonPlayer pokemonPlayer = PokemonPlayerManger.INSTANCE.getPokemonPlayer(targetUUID);
        int size = pokemonPlayer.getPcBoxSize();

        Function<Pokemon, ItemStack> function = player.hasPermission("LGPokemonMenu.to_item") ? LGPokemonMenu.getGuiItem()::getPcPokemon : LGPokemonMenu.getGuiItem()::getPcPokemonNoToItem;
        ItemStack air_pokemon = player.hasPermission("LGPokemonMenu.edit") ? LGPokemonMenu.getGuiItem().getEditAirPoke() : LGPokemonMenu.getGuiItem().getAirPoke();
        for (int i = 0; i <= 35; i++) {
            int slot = POKEMON_ARRAY[i];
            Pokemon pokemon = i < 6 ? pokemonPlayer.getPartyPokemon(i) : pokemonPlayer.getPCPokemon(page, i - 6);
            ItemStack item = pokemon == null ? air_pokemon : function.apply(pokemon);
            inventory.setItem(slot, item);
        }
        if (select != null) {
            int slot = -1;
            if (select.isPC() && select.getBox() == page) {
                slot = POKEMON_ARRAY[select.getSlot() + 6];
            } else if (select.isParty()) {
                slot = POKEMON_ARRAY[select.getSlot()];
            }
            if (slot >= 0) {
                Pokemon pokemon = pokemonPlayer.getPokemon(select);
                if (pokemon != null) {
                    inventory.setItem(slot, LGPokemonMenu.getGuiItem().getSelectPokemon(pokemon));
                }
            }
        }
        if (remove != null) {
            int slot = -1;
            if (remove.isPC() && remove.getBox() == page) {
                slot = POKEMON_ARRAY[remove.getSlot() + 6];
            } else if (remove.isParty()) {
                slot = POKEMON_ARRAY[remove.getSlot()];
            }
            if (slot >= 0) {
                Pokemon pokemon = pokemonPlayer.getPokemon(remove);
                if (pokemon != null) {
                    inventory.setItem(slot, LGPokemonMenu.getGuiItem().getRemovePokemon(pokemon));
                }
            }
        }
        for (int slot : GLASS_ARRAY) {
            inventory.setItem(slot, LGPokemonMenu.getGuiItem().getBorder());
        }
        if (player.hasPermission("LGPokemonMenu.show.pc")) {
            inventory.setItem(46, LGPokemonMenu.getGuiItem().getShowPC());
        } else {
            inventory.setItem(46, LGPokemonMenu.getGuiItem().getBorder());
        }
        if (player.hasPermission("LGPokemonMenu.search")) {
            inventory.setItem(51, LGPokemonMenu.getGuiItem().getSearch());
        } else {
            inventory.setItem(51, LGPokemonMenu.getGuiItem().getBorder());
        }
        if (player.hasPermission("LGPokemonMenu.sort")) {
            inventory.setItem(53, LGPokemonMenu.getGuiItem().getSort());
        } else {
            inventory.setItem(53, LGPokemonMenu.getGuiItem().getBorder());
        }
        inventory.setItem(49, LGPokemonMenu.getGuiItem().getBack());
        inventory.setItem(48, LGPokemonMenu.getGuiItem().getPreviousPageJump(page + 1, size));
        inventory.setItem(50, LGPokemonMenu.getGuiItem().getNextPageJump(page + 1, size));
    }

    @Override
    public void onInventoryClick(ClickInventoryContext context) {
        context.setCancelled(true);
        Player player = context.getPlayer();
        int slot = context.getSlot();
        ClickType click = context.getClick();
        PokemonPlayer pokemonPlayer = PokemonPlayerManger.INSTANCE.getPokemonPlayer(targetUUID);
        int size = pokemonPlayer.getPcBoxSize() - 1;

        Position position = slotToPokemonSlot(slot);
        if (position != null) {
            handlePokemonSlotClick(player, click, pokemonPlayer, position);
        } else if (slot == 48) {
            int nextPage = page - 1;
            if (click == ClickType.SHIFT_LEFT || click == ClickType.SHIFT_RIGHT) {
                nextPage = page - 10;
            }
            page = nextPage < 0 ? size : nextPage;
            onDrawInventory(player);
            player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 0.5F, 1F);
        } else if (slot == 50) {
            int nextPage = page + 1;
            if (click == ClickType.SHIFT_LEFT || click == ClickType.SHIFT_RIGHT) {
                nextPage = page + 10;
            }
            page = nextPage > size ? 0 : nextPage;
            onDrawInventory(player);
            player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 0.5F, 1F);
        } else if (slot == 49) {
            new PartyInventor(targetUUID).openInventory(player);
            player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 0.5F, 1F);
        } else if (slot == 46 && player.hasPermission("LGPokemonMenu.show.pc")) {
            int remainingCooldown = DisplayPokemonManger.INSTANCE.getRemainingCooldown(player.getUniqueId());
            if (remainingCooldown > 0 && !player.hasPermission("LGPokemonMenu.bypass.show.cooldown")) {
                player.sendMessage(LGPokemonMenu.getMessage().getDisplayCooldown(remainingCooldown / 1000));
                player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1.0F, 1.0F);
                return;
            } else {
                DisplayPokemonManger.INSTANCE.addCooldown(player.getUniqueId());
                player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 0.5F, 1F);
            }
            Pokemon[] pokemonArray = new Pokemon[36];
            for (int i = 0; i < 36; i++) {
                Position tempPosition = i < 6 ? new Position(i) : new Position(page, i - 6);
                Pokemon pokemon = pokemonPlayer.getPokemon(tempPosition);
                if (pokemon != null) {
                    pokemonArray[i] = pokemon;
                }
            }
            PokemonDisplayHandler.showPCPokemon(pokemonArray, player.getName());
        } else if (slot == 51 && player.hasPermission("LGPokemonMenu.search")) {
            search = true;
            player.closeInventory();
            player.sendMessage(LGPokemonMenu.getMessage().getInputPokemon());
            PlayerInputManager.waitForInput(player, InputType.POKEMON_PROPERTIES, this);
            player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1.0F, 1.8F);
        } else if (slot == 53 && player.hasPermission("LGPokemonMenu.sort")) {
            new SortInventor(targetUUID, page).openInventory(player);
            player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 0.5F, 1F);
        }
    }

    @Override
    public void onInventoryClose(InventoryContext context) {
        super.onInventoryClose(context);
        restoreMainHand(context.getPlayer().getInventory());
    }

    @Override
    protected Position getEmptySlot(PokemonPlayer pokemonPlayer, Position position) {
        return position.isParty() ? pokemonPlayer.getEmptyPCSlot(page) : pokemonPlayer.getEmptyPartySlot();
    }

    @Override
    protected Position slotToPokemonSlot(int slot) {
        for (int i = 0; i < POKEMON_ARRAY.length; i++) {
            if (POKEMON_ARRAY[i] == slot) {
                return i < 6 ? new Position(i) : new Position(page, i - 6);
            }
        }
        return null;
    }

    @Override
    public void onPlayerInput(Player player, String input) {
        if (!search) {
            super.onPlayerInput(player, input);
            return;
        }
        search = false;
        PokemonProperties properties = PokemonPropertiesArgumentType.INSTANCE.parse(input);
        new SearchInventor(targetUUID, properties).openInventory(player, this);
    }

}
